
#ifndef BVH_CU
#define BVH_CU

#include "../BVH.hpp"
#include "dev_utils.hpp"
#include "../host_utils.hpp"
#include "../Triangle.hpp"



__device__ Intersection BVHAccel::Intersect(const Ray &ray) const
{
    Intersection isect;
    if (!root){
        return isect;
    }
    isect = BVHAccel::getIntersection(root, ray);
    return isect;
}

__device__ Intersection BVHAccel::getIntersection(BVHBuildNode *node, const Ray &ray) const
{
    // TODO Traverse the BVH to find intersection

    bool dirIsNeg[3] = {ray.direction.x < 0, ray.direction.y < 0, ray.direction.z < 0};
    Intersection inter;

    if (node->left == nullptr && node->right == nullptr)
    {
        if (!node->bounds.IntersectP(ray, ray.direction_inv, dirIsNeg))
        {
            return inter;
        }

        if(node->object->subClassType==1){
            return ((MeshTriangle *)node->object)->getIntersection(ray);
        }
        else if(node->object->subClassType==2){
            return ((Triangle *)node->object)->getIntersection(ray);
        }
        else{
            printf("UnImplement Object's subclass\n");
            printf("----------------------ERROR RESULT----------------------\n");
            return ((MeshTriangle *)node->object)->getIntersection(ray);
        }
    }
    if (node->bounds.IntersectP(ray, ray.direction_inv, dirIsNeg))
    {
        Intersection hit_left = getIntersection(node->left, ray);
        Intersection hit_right = getIntersection(node->right, ray);
        return hit_left.distance < hit_right.distance ? hit_left : hit_right;
    }
    else
    {
        return inter;
    }
}

__device__ void BVHAccel::getSample(BVHBuildNode *node, float p, Intersection &pos, float &pdf,int thread_id)
{
    if (node->left == nullptr || node->right == nullptr)
    {
        if(node->object->subClassType==1)
            ((MeshTriangle *)node->object)->Sample(pos, pdf,thread_id);
        else if(node->object->subClassType==2)
            ((Triangle *)node->object)->Sample(pos, pdf,thread_id);
        else{
            printf("UnImplement Object's subclass\n");
            printf("----------------------ERROR RESULT----------------------\n");
        }
        pdf *= node->area;
        return;
    }
    if (p < node->left->area)
        getSample(node->left, p, pos, pdf,thread_id);
    else
        getSample(node->right, p - node->left->area, pos, pdf,thread_id);
}

__device__ void BVHAccel::Sample(Intersection &pos, float &pdf,int thread_id)
{
    float p = sqrt(get_random_float(thread_id)) * root->area;
    getSample(root, p, pos, pdf,thread_id);
    pdf /= root->area;
}

#endif
